package example.aspect;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;

import java.util.Arrays;

/**
 * 切面类
 * 切入点表达式：
 *      public int example.service.MathService.div(int, int) 指定具体方法具体参数
 *      public int example.service.MathService.*(..) 全部方法 *
 *  ！！！ 如果要得到 JoinPoint， JoinPoint类型的参数必须是回调方法的第一个参数，否则无法识别
 */

//声明切面类并加入容器
@Aspect
@Component
public class LogAspect {

    /**
     * 抽取公共的切入点表达式
     * 本类引用注解内写方法名小括号 @Before("pointCat()")
     * 外部类引用写全类命名
     */
    @Pointcut("execution(public int example.aop.MathService.*(..))")
    public void pointCut() {}


    /**
     * 前置通知
     */
    @Before("pointCut()")
    public void before(JoinPoint joinPoint) {
        String name = joinPoint.getSignature().getName();
        Object[] args = joinPoint.getArgs();
        System.out.println("方法" + name + "运行，参数列表是：" + Arrays.toString(args) );
    }

    /**
     * 后置通知
     * ！ 方法执行后,无论正常结束还是异常结束，都会调用
     */
    @After("pointCut()")
    public void after(JoinPoint joinPoint) {
        System.out.println("方法 " + joinPoint.getSignature().getName() + " 执行结束");
    }

    /**
     * 返回通知
     */
    @AfterReturning(value = "pointCut()", returning = "result")
    public void afterReturn(JoinPoint joinPoint, Object result) {
        System.out.print("方法 " + joinPoint.getSignature().getName() + " 正常返回 ");
        System.out.println("返回值是：" + result);
    }

    /**
     * 异常通知
     */
    @AfterThrowing(value = "pointCut()", throwing = "ex")
    public void exception(JoinPoint joinPoint, Exception ex) {
        System.out.print("方法 " + joinPoint.getSignature().getName() + " 抛出异常 ");
        System.out.println("异常信息是：" + ex.getLocalizedMessage());
    }


}



